The Strong and the Weak

Dec.15, 2021


Tianrun Zhang, tz395
Tongqing Zhang, tz422

Objective

Having watched several videos of projects developed by the previous team on the website, as fanatic game players, we decided without hesitation to make an RPG game using some kind of game consoles (which was later designed as a gyroscope) as its controller. The first game that comes to mind is ‘Feeding Frenzy’, which was a very simple game that used to be so famous. To make the game more interesting, we also decided to add some functions and characters, which we will talk about later.

Video

For brief introduction and actual operation of our game, you can see the link below:
The Strong and the Weak

Introduction

The main idea of this project ‘The Strong and the Weak’ comes from a famous game launched by EA – ‘Feeding Frenzy’ that was widely spread in 2000s. In this game, you control a fish which is very small and weak at the very beginning using a mouse and seek for weaker prey while avoiding horrible predator that is bigger than you. Having grown larger and larger by hunting other preys, you will be able to eat more kinds of fish in the sea and finally become the king of that area.
It’s really a fascinating game and thus in this project, it will be implemented on the Raspberry Pi using pygame in which you can control the character by a keyboard and a triple-axis accelerometer rather than a mouse. In addition, instead of acting a fish, it would be more interesting to be an adventurer wandering in a fantasy world, therefore, characters like demon, cat, and rocket are designed in our game.

  This is a picture


   This is a picture

          Figure 1. Game interface and whole device

Design

Characters


 Player (two modes)
 Weakest prey: Red fish, bonus coin
 Growth enemy: Cat (can grow bigger after eating certain number of fishes)
 Stronger enemy: Demon (can chase player when they are weak and avoid  as they grow stronger)
 Predator: Bigball (comes from Super Mario)
 Disaster: Rocket (destroy everything in front of it)
 Functional props: Banana (slow down player’s speed), Energy drink (boost  player’s speed), Snake (initial player’s size)




Functions


 Menu
 Movement
 Interactions
 Files loading(picture and music)

Here is the general logic of the program:



This is a picture

             Figure 2. General logic of program



   This is a picture

                Figure 3. start menu



   This is a picture

               Figure 4. Pause menu




Implementation


Step1: Character Design
We designed characters in this game based on several MMORPG games we played before including Maplestory, Super Mario, Dragon Ball, etc. We drew most of the pictures for the characters we designed via notability while downloaded and modified the other on the Internet.
There are 4 types of characters in this game including player itself, enemies, disaster and functional props. The first type enemies are preys including redfish, small cat and bonus coin that the player can directly eat them to get score as well as growing larger; The second kind of enemies are some other stronger ones including demon, big cat and bigball. Though they can beat us as predators when we are weaker, the players will be able to kick them back once they have accumulated enough power or even get a super power;

   This is a picture

                Figure 5. Preys


   This is a picture

                Figure 6. Predators


For the rocket (3rd kind of character), we call it ‘disaster’ because it is invincible and will destroy everything on the way. The only thing we can do is avoiding it unless we get the super power (Still cannot eat it); The last type of characters are functional props including banana peel, energy drink and snake which may give player different kinds of buff or debuff. The banana peel slow player’s speed down while the energy drink boost player’s speed. A snake will bite the player, making them back to the original size and weaker again. So, to be careful!

   This is a picture

                Figure 7. Rocket


To build such characters, we used one popular module of pygame called ‘pygame.sprite.Sprite’ which is the simple base class for visible game objects. Then we constructed a class for each one and add them to a group called ‘pygame.sprite.Group’ that is a container class to hold and manage multiple Sprite objects. In each class we are able to initialize the character and many parameters for them, which makes our life a lot easier.


Step2: Character Movement
For the movements of characters, we only designed several simple patterns such as making them wander within the screen with a random speed and direction, moving from one side to another side, restricting the area of movements except for the demon and snake. For the demon, we gave it more intelligence by citing a function from a prototype we found on GitHub. The demon is able to chase weaker player while avoiding stronger one. But this design causes some bugs that the demon can only show up from the top of screen and also leave from top. We also used the design from the prototype for the movements of snake. The movement of snake contains 4 pictures which will be displayed in cycle when it walks through the grass from one side to another at the bottom of the screen.
For player itself, we can control its movement using keyboard or the gyroscope connected to the Raspberry Pi. The player is able to move in 8 different directions including up, down, left, right, upleft, upright, downleft, downright. We planned to add more possible angles with adjustable speed of movement for the gyroscope but failed. This might be one of our goals in the future, which can make the movement much more smoothly and intuitively.


   This is a picture

     This is a picture

            Figure 8. Demon is chasing the player


Step3: Character Interaction
Correct interactions between characters are the most important in our mind. We carefully defined interactions between one character and others that may affect it. For preys, predators and functional props, they should either simply disappear by killing themselves or call the function to end the game when colliding with the player. The disaster just ‘kills’ everything on its way. But for the player, there are multiple parameters should be updated when colliding with different kind of characters. We just defined the function for collision with others in the class of player one by one to guarantee they can work well.
In fact, there are 4 parameters with the highest frequency of change which are scores (including total scores and size scores), speed, timer for special effects on the player and finally the super power switch. To make the players’ life easier, we added a cheating function for them that is the super power. Players are able to activate a super golden mode by simply pressing the key ‘S’ or jittering the gyroscope slightly with no limit like cooldown. In this mode, the player becomes invincible, gaining the power to beat any enemies except for the rocket (but the rocket cannot beat the player either) and higher speed to get scores more efficiently.
Then in the main loop of the game, we used pygame.sprite.collide_mask to detect collision between two sprites, which we thought is the best way because the shape of most characters is irregular. Once two sprites collide, the program calls the function defined in their class to update their status.


  This is a picture

             Figure 9. Super golden mode


Step4: Accelerometer Installation

The LIS3DH accelerometer needs 3V to power, so we can use the 3.3V pin on Raspberry Pi. Because we use I2C(instead of SPI) to transfer data from accelerometer to Raspberry Pi, so the sensor SCL and SDA should be connected to Raspberry Pi's SCL and SDA pin respectively. In addition, GPIO 6 was chosen because it is a general pin and does not have other uses reserved by the Raspberry Pi thus would be better for us to use directly(without disabling any function else). The wiring of the accelerometer(using i2c) is listed as follows:
    Pi 3V3 -> sensor Vin
    Pi GND -> sensor GND
    Pi SCL -> sensor SCL
    Pi SDA -> sensor SDA
    Pi GPIO6 -> sensor INT


    This is a picture
    This is a picture

       Figure 10. Accelerometer wiring (from  learn.adafruit.com)



To use the triple-axis accelerometerr, adafruit's CircuitPython library bundle were installed. In addition, the Adafruit_Blinka library which provides the CircuitPython support in Python are also necessary. After following the installation tutorial on learn.adafruit.com, we enabled the I2C on Raspberry Pi to transfer data by setting in the Rasp-config interface, and used the command 'sudo pip3 install adafruit-circuitpython-lis3dh' to install the lis3dh library directly. After that, the accelerometer's installation was done!

Testing

For hardware testing, in order to obtain the acceleration data from triple-axis accelerometer, we had the SDA pin and SCL pin connected to Raspberry Pi, so that the accelerometer can transfer the data it measured to Pi. To test it, we wrote a test program, which can print the data coming from accelerometer to the screen. To achieve that, we first imported the necessary modules(installed before) and initialized the I2C connection with the accelerometer:


    This is a picture

             Figure 11. Initialization


After that, values can be read from the sensor by calling the lis3dh.acceleration property, this will return the x, y, z acceleration values in a 3-tuple in m / s ^ 2, and print the values continuously using a while loop:


        This is a picture

              Figure 12. Get acceleration


The values in the 3-tuple show the acceleration in 3 directions, so when we put the accelerometer horizontally, the z nearly equals to 9.8, which is the acceleration of gravity.
Besides, we also encountered some troubles with the gyroscope while using it as the controller to play the game. Simply put, it’s about the sensitivity of detection. As we only designed 8 directions for the player to move with a consistent speed, it’s very important and difficult to set a suitable trigger threshold for the gyroscope. At the same time there is an inevitable problem that the angle needed for moving like upright is a little more than moving right directly. This is because the gyroscope only detects the direction of gravity and it can only have one direction with full gravity, which means there is no way for both x and y axis to get full gravity simultaneously (Gravity needs to be distributed as vector). So, the player must tilt a larger angle to make the character move in both directions at the same time such as upright. And this may be solved when we implement 360 movement for the character in the future.



For software testing, the most challenging part is how to make it playable on the small 320x240 PiTFT screen. As we designed the game on our PC with a resolution of about 900x600 at the beginning, most parameters in the game are set to fit this resolution including position of invisible walls, icons and texts displayed on the top of the screen, speed designed for characters, size of pictures that suitable for the resolution.
So, when we first tried to run on a smaller PiTFT screen, it caused a lot of problems such as exceeding parameters’ range, characters are too big to move correctly in the screen, display of icons and texts are weird. Then we spent much of time to redesign almost all the things to adapt the game to smaller resolution. For the very first, we cut down the size of nearly all pictures for the characters and icons while keeping their aspect ratio unchanged. Then we redesigned the position for icons and texts displayed in the screen. Finally, we adjusted the speed and position for all characters one by one to make sure that the game works well on the PiTFT screen.

Results 
Conclusion

In this project, we have successfully developed the game 'The Strong and the Weak' running both on Raspberry Pi 4 and PC. To run this game on Pi TFT, we carefully set the resolution of all characters as well as buttons. To control the moving of the character, an triple-axis accelerometer is used to detect and measure the direction of gravity. When the acceleration reach the threshold, the program would see it as a moving command. Under the long time testing, the accelerometor control was proved to be very accurate and reliable. Besides, we also defined several different characters like the demon, cat, and rocket to make the game more interesting. With the help of pygame, we also developed many functions to implement the game logic such as the menu, eat, and golden mode of the character(which make the character invincible for 5 seconds), and all of them performed as planned.
In general, although some aspects(listed in the future work part) can be further improved, our game was completely developed and works very well for now!

Future Work

If more time were given, our game can be improved from following aspects:

1. Improve the smoothness of character movement by resetting the threshold of the three directions(x, y, z) output by the accelerometer.
2. Solve the problem that some characters looks weird when hitting the wall and change their speed for several times.
3. Improve the accuracy of the timer, which does not work well with time.sleep() function in the loop.
4. Fix the memory running out problem that happened after long time of playing.
5. Try to make the program run in mutithread (running in single thread may cause lag).

Budget

Raspberry Pi 4: $35
Pi TFT: $30
LIS3DH Triple-Axis Accelerometer: $11
Total: $76

Contributions

Tianrun Zhang: hardware connection, installation, debugging and testing
Tongqing Zhang: character design, software development and testing

Code Appendix

The codes for this project is too long to put them here, so we've uploaded the codes in Github Repository

Contact


    team_photo

              Figure 13. Team photo

         left: Tianrun Zhang    right: Tongqing Zhang
         tz395@cornell.edu    tz422@cornell.edu